package com.softeem.shiro;

import cn.hutool.core.bean.BeanUtil;
import com.softeem.pojo.Admin;
import com.softeem.pojo.SysPermission;
import com.softeem.pojo.SysRole;
import com.softeem.service.AdminService;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 1. 实现认证身份功能
 * 2. 进行权限配置
 * 3. 支持jwt的凭证校验
 */
@Component
@Slf4j
public class AccountRealm extends AuthorizingRealm {
    @Autowired
    AdminService adminService;

    JwtUtils jwtUtils=new JwtUtils();

    // 只有当需要检测用户权限的时候才会调用此方法，例如@RequiresRoles,@RequiresPermissions之类的
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        log.info("----------授权----------");
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        AccountProfile  obj = (AccountProfile) principalCollection.getPrimaryPrincipal();
        log.info("----------授权----------"+obj);
        Admin adminInfo = adminService.getAdmin(obj.getId());
        System.out.println(adminInfo);
        for(SysRole role:adminInfo.getRoleList()){
            //将角色放入SimpleAuthorizationInfo
            info.addRole(role.getRole());
            //获取用户的权限
            for (SysPermission p:role.getPermissions()){
                info.addStringPermission(p.getPermission());
            }
        }
        return info;
    }

    //  @RequiresAuthentication 在需要用户认证和鉴权的时候才会调用
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
            throws AuthenticationException {
        log.info("----------认证----------");
        JwtToken jwtToken = (JwtToken) token;
        Claims claim = jwtUtils.getClaimByToken((String) jwtToken.getPrincipal());
        String adminId = claim.getSubject();
        System.out.println("adminId = " + adminId);
        //调用service层中的按方法
        Admin admin = adminService.getAdmin(Integer.valueOf(adminId));
        if (admin == null) {
            //抛出异常，账户不存在
            throw new UnknownAccountException("账户不存在");
        } else if (admin.getStatus() == 2) {
            //抛出异常，账户被锁定
            throw new LockedAccountException("账户已被锁定");
        }
        // 身份信息，用户基本信息，密钥信息，名字
        AccountProfile profile = new AccountProfile();
        BeanUtil.copyProperties(admin, profile);
        //返回给shiro
        return new SimpleAuthenticationInfo(profile, jwtToken.getCredentials(), getName());
    }

    // 支持jwt的凭证校验
    //根据token判断此Authenticator是否使用该realm
    //必须重写不然shiro会报错
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }
}

